package com.wdm.sms.service.user.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wdm.sms.commonutil.enums.ResponseEnum;
import com.wdm.sms.commonutil.config.exception.MyException;
import com.wdm.sms.commonutil.jwt.JwtHelper;
import com.wdm.sms.commonutil.utils.jwt.JwtTokenUtils;
import com.wdm.sms.commonutil.utils.r.R;
import com.wdm.sms.commonutil.utils.result.Result;
import com.wdm.sms.commonutil.utils.result.ResultCodeEnum;
import com.wdm.sms.commonutil.utils.md5.MD5;
import com.wdm.sms.entity.common.dto.page.PageDTO;
import com.wdm.sms.entity.User;
import com.wdm.sms.entity.common.dto.user.LoginDTO;
import com.wdm.sms.entity.common.dto.user.UserDTO;
import com.wdm.sms.entity.common.dto.user.token.UserTokenDTO;
import com.wdm.sms.entity.common.vo.user.LoginVo;
import com.wdm.sms.entity.common.vo.user.UpdatePasswordUserVO;
import com.wdm.sms.entity.system.SysUser;
import com.wdm.sms.mapper.UserMapper;
import com.wdm.sms.service.redis.RedisService;
import com.wdm.sms.service.user.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wudaiming
 * @since 2023-03-03
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private final UserMapper userMapper;
    private final RedisService redisService;
    @Override
    public R<Page<User>> getAllUsers(PageDTO pageDTO) {
        //参数一：当前页
        //参数二：页面大小
        Page<User> page = new Page<>(pageDTO.getCurrent(), pageDTO.getPageSize());
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("deleted","0");
        return R.ok(userMapper.selectPage(page, query));
    }

    @Override
    public Result addUser(UserDTO userDTO) {
        User user=new User();
        //密码进行MD5加密
        userDTO.setPassword(MD5.encrypt(userDTO.getPassword()));
        BeanUtils.copyProperties(userDTO, user);
        return Result.build(this.save(user),ResultCodeEnum.SUCCESS);
    }

    @Override
    public Result updateUser(UserDTO userDTO) {
        User user=new User();
        BeanUtils.copyProperties(userDTO, user);
        return Result.build(this.saveOrUpdate(user),ResultCodeEnum.SUCCESS);
    }

    @Override
    public Result deleteUser(String id) {
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getId,id);
        return Result.build(userMapper.delete(queryWrapper),ResultCodeEnum.SUCCESS);
    }

    @Override
    public Result login(LoginVo loginVo) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name",loginVo.getUserName());
        User user = userMapper.selectOne(queryWrapper);
        if(user == null) {
            throw new MyException(ResponseEnum.USER_EX);
        }
        //1 判断密码
        //数据库存密码（MD5）
        String password_db = user.getPassword();
        //获取输入的密码
        String password_input = MD5.encrypt(loginVo.getPassword());
        if(!password_db.equals(password_input)) {
            throw new MyException(ResponseEnum.PASSWORD_EX);
        }
        //2 使用jwt根据用户userName和用户密码password生成token字符串
        UserTokenDTO userTokenDTO = new UserTokenDTO();
        BeanUtils.copyProperties(userTokenDTO, loginVo);
        userTokenDTO.setName(user.getName());
        userTokenDTO.setGmtCreate(System.currentTimeMillis());
        String token = JwtHelper.createToken(userTokenDTO.getName(),userTokenDTO.getGmtCreate());
        //String token = JwtHelper.createToken(user.getName(), user.getPassword());
        //3.存入token至redis
        redisService.set(user.getName()+"-token", token);
        //4 返回
        Map<String,Object> map = new HashMap<>();
        map.put("token",token);
        return Result.build(map,ResultCodeEnum.SUCCESS);
    }

    public User getUserByName(String userName) {
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("name",userName);
        //Wrappers<>.lambdaQuery()
        return userMapper.selectOne(query);
    }

    @Override
    public User getUser(LoginDTO loginDTO) {
        QueryWrapper<User> query=new QueryWrapper<>();
        query.eq("name",loginDTO.getUserName())
                .eq("password",loginDTO.getPassword());
        return userMapper.selectOne(query);
    }

    @Override
    public R updatePassword(UpdatePasswordUserVO updatePasswordUserVO) {
        //1.修改密码
        //User user = User.builder().password(updatePasswordUserVO.getPassword())
        //        .name(updatePasswordUserVO.getName())
        //        .build();
        LambdaQueryWrapper<User> lambdaQuery = Wrappers.<User>lambdaQuery();
        lambdaQuery.eq(User::getName,updatePasswordUserVO.getName());
        User user = userMapper.selectOne(lambdaQuery);
        if (user == null) {
            throw new MyException(ResponseEnum.USER_EX);
        }
        LambdaUpdateWrapper<User> lambdaUpdate=Wrappers.<User>lambdaUpdate();
        lambdaUpdate.set(User::getPassword,MD5.encrypt(updatePasswordUserVO.getPassword()))
                .eq(User::getName,updatePasswordUserVO.getName());
        userMapper.update(user,lambdaUpdate);
        //2.生成新的token
        //UserTokenDTO userTokenDTO = UserTokenDTO.builder()
        //        .name(updatePasswordUserVO.getName())
        //        .gmtCreate(System.currentTimeMillis()).build();
        UserTokenDTO userTokenDTO = new UserTokenDTO();
        userTokenDTO.setName(updatePasswordUserVO.getName());
        userTokenDTO.setGmtCreate(System.currentTimeMillis());
        String token = JwtTokenUtils.generateToken(userTokenDTO);
        //3.更新token
        redisService.set(user.getName(), token);
        return R.ok(token);
    }
}
